#include <buola/buola.h>

#ifdef BUOLA_HAVE_DC1394

#include <buola/media/video/b1394source.h>
#include <buola/container/cbufferconsumer.h>

#include "cdc1394.h"

#include <dc1394/conversions.h>
#include <dc1394/register.h>
#include <dc1394/utils.h>

namespace buola { namespace media {

B1394Source::B1394Source(int pCamNumber,const std::string &pName)
    :   BBox(pName)
    ,   mCamNumber(pCamNumber)
    ,   mDone(false)
    ,   oImage(this,"image out")
{
}

B1394Source::~B1394Source()
{
}

void B1394Source::ThreadCB()
{
    assert(GetState()==STATE_ACTIVE);

    while(!mDone)
    {
        dc1394video_frame_t *lFrame;

        mCamera->DequeueFrame(&lFrame);

        unsigned char *lPtr=(unsigned char*)lFrame->image;

        int lW = lFrame->size[0];
        int lH = lFrame->size[1]*2;

        unsigned char lTmpBuf[lW*lH];
        img::CImage_rgb8 lImage(CSize_i(lW,lH),oImage.Allocator());
        unsigned char *lBuf=lImage.RawBytes();

        dc1394_deinterlace_stereo(lPtr,lTmpBuf,lW,lH);
        dc1394_bayer_decoding_8bit(lTmpBuf,lBuf,lW,lH,DC1394_COLOR_FILTER_GRBG,DC1394_BAYER_METHOD_HQLINEAR);

        mCamera->EnqueueFrame(lFrame);

        oImage=std::move(lImage);
        PushAtomicOutputs();
    }
}

void B1394Source::DoInitialize()
{
    mCamera=CDC1394::Get()->GetCamera(mCamNumber);

    mCamera->Initialize(true);

//    SetWhiteBalance(63,23);

//    dc1394video_mode_t lMode = DC1394_VIDEO_MODE_FORMAT7_0;
    dc1394video_mode_t lMode = DC1394_VIDEO_MODE_640x480_YUV422;

//    SetImageSize(mSize,lMode);
//    SetImagePos(CIntPoint(0,0),lMode);

    mCamera->SetFrameRate(DC1394_FRAMERATE_15);
    mCamera->SetISOSpeed(DC1394_ISO_SPEED_400);
    mCamera->SetMode(lMode);

//    dc1394_video_set_iso_channel(mP->mDC1394Camera, mCamNumber);

}

void B1394Source::DoActivate()
{
    mCamera->Start();

    uint32_t lBayer=mCamera->GetControlRegister(0x1040);

    switch(lBayer)
    {
    case 0x52474742:
        mCamera->SetBayerFilter(DC1394_COLOR_FILTER_RGGB);
        break;
    case 0x47425247:
        mCamera->SetBayerFilter(DC1394_COLOR_FILTER_GBRG);
        break;
    case 0x47524247:
        mCamera->SetBayerFilter(DC1394_COLOR_FILTER_GRBG);
        break;
    default:
        mCamera->SetBayerFilter(DC1394_COLOR_FILTER_BGGR);
    }

    mCamera->SetFeature(0,160);
    /*
    dc1394_feature_set_mode(mP->mDC1394Camera,DC1394_FEATURE_EXPOSURE,DC1394_FEATURE_MODE_MANUAL);
    dc1394_feature_set_power(mP->mDC1394Camera,DC1394_FEATURE_EXPOSURE,DC1394_OFF);
    dc1394_feature_set_value(mP->mDC1394Camera,DC1394_FEATURE_EXPOSURE,336);
    dc1394_feature_set_mode(mP->mDC1394Camera,DC1394_FEATURE_SHUTTER,DC1394_FEATURE_MODE_MANUAL);
    //    dc1394_feature_set_value(mP->mDC1394Camera,DC1394_FEATURE_SHUTTER,50);
    dc1394_feature_set_value(mP->mDC1394Camera,DC1394_FEATURE_SHUTTER,(mCamNumber<2)?200:350);
    dc1394_feature_set_mode(mP->mDC1394Camera,DC1394_FEATURE_GAIN,DC1394_FEATURE_MODE_MANUAL);
    //    dc1394_feature_set_value(mP->mDC1394Camera,DC1394_FEATURE_GAIN,120);
    dc1394_feature_set_value(mP->mDC1394Camera,DC1394_FEATURE_GAIN,250);
*/
}

void B1394Source::DoDeactivate()
{
    mDone=true;
    sleep(chrono::seconds(1));

    mCamera->Stop();
}

/*namespace media*/ } /*namespace buola*/ }

#endif
